home *** CD-ROM | disk | FTP | other *** search
- Path: bcarh8ab.bnr.ca!jcobban
- From: jcobban@bnr.ca (Jim Cobban)
- Newsgroups: comp.lang.c++
- Subject: Deriving class from IOSTREAMs
- Date: 15 Apr 1996 19:59:06 GMT
- Organization: Bell-Northern Research Canada
- Message-ID: <4ku9qa$7mt@bcarh8ab.bnr.ca>
- Reply-To: jcobban@nortel.ca (Jim Cobban)
- NNTP-Posting-Host: bcarsf1f.bnr.ca
-
- I am trying to define a class which has the following characteristics:
-
- 1) It supports the insertion (<<) operator of the ostream class.
- 2) Output is organized into units of work. No part of a unit of work
- can be written to the output device until the unit of work is complete.
- Then all of the text in the unit of work must be placed on the same line
- of output. In other words if there is enough room on the current line
- to hold all of the text then it will be printed on the current line,
- otherwise a new line is started and the text is written on the new line.
- 3) When a new line is started, including the very first line in the output,
- an application specified prefix is written before the first unit of
- work.
-
- The first requirement dictates that my class be derived directly or
- indirectly from ostream. The second requirement seems to me to dictate that
- my class be derived, in particular, from ostrstream, which provides a buffer
- in which output can be held until a unit of work is complete. I would like
- the end of a unit of work to be signalled by a manipulator, but I have had a
- great deal of difficulty in getting that to work.
-
- A stripped down sample program which illustrates some of the problems I am
- having follows:
-
- 10 #include <strstream.h>
- 11
- 12 class xstream : public ostrstream
- 13 {
- 14 char buffer[80];
- 15
- 16 public:
- 17
- 18 xstream();
- 19 friend ostream& operator <<(ostream& Ostream, ostream & (*
- func)(xstream &))\
- 20 { return (*func)((xstream &)Ostream); }
- 21 }; //* end of declaration of class xstream
- 22
- 23 xstream::xstream()
- 24 {
- 25 rdbuf()->setbuf(buffer, sizeof(buffer));
- 26 }
- 27
- 28 ostream & endw(xstream & Stream)
- 29 {
- 30 Stream << ends;
- 31 cout << "pcount=" << Stream.pcount() << " \"" << Stream.str() <<
- "\"" << endl;
- 32 Stream.seekp(0, ios::beg);
- 33 return Stream;
- 34 }
- 35
- 36 int main()
- 37 {
- 38 xstream os;
- 39 double pi=3.14159;
- 40
- 41 cout << "pi=" << pi << " and so on" << endl;
- 42 os << "pi=" << pi << " and so on" << endw;
- 43 os << "testing" << endw;
- 44 os << "short" << endw;
- 45 os << "testing " << 5 << " more";
- 46 cout << "outside os.pcount()=" << os.pcount() << endl;
- 47 os << endw;
- 48 }
-
- The first problem is that the behavior of my manipulator for signalling the
- end of a unit of work is dependent upon access to methods of the xstream
- class (In the example these are all methods of the ostrstream class, but that
- is because I haven't included the code for printing the prefix in this
- example). But normal manipulators, like endl, take an ostream as their
- parameter. So I have the ugly, dangerous, cast in the definition of the
- operator << in line 19, which exists only to convince C++ to call endw. I
- say dangerous because there is nothing to prevent the endw manipulator from
- being called for any output stream. As a specific example the statement
- "cout << endw;" compiles cleanly, but would crash because the stream is not
- actually an ostrstream. But the only alternatives I can see are:
-
- 1) invoke endw as a member function of xstream, rather than as a
- manipulator, which is syntactically clumsy.
- 2) redefine all of the inserters under xstream so that they return
- references to xstream rather than to ostream, something I can't do
- because the original operators were not defined as virtual, for obvious
- performance reasons.
-
- Quite aside from that, although the above example compiles cleanly, it does
- not produce the expected output, for reasons which escape me. The actual
- output is:
-
- pi=3.14159 and so on
- pcount=-268438404 "pi=3"
- pcount=-268438407 ""
- pcount=-268438407 ""
- outside os.pcount()=0
- pcount=-268438407 ""
-
- The first line is the result of line 41 above. The lines starting with
- pcount are produced by the endw manipulator. There are a couple of glaring
- problems:
-
- 1) the value of pcount is garbage.
- 2) the inherited inserters don't seem to work, starting with the
- inserter for double which stopped after putting out one digit. Nothing
- comes out for any subsequent inserter.
- 3) if I omit using the double inserter then in other examples I got
- more reasonable output, except that the ends manipulator seemed
- incapable of shortening the string. For example if I deleted lines 41
- and 42 from the test program then the output of lines 43 and 44 is
-
- pcount=-268438401 "testing"
- pcount=-268438403 "shortng"
-
- If I cannot quickly resolve this bizarre behavior then I am simply going to
- conclude that the C++ IOSTREAMS system is completely fucked up, and go back
- to using printf.
- --
- Jim Cobban | jcobban@nortel.ca | Phone: (613) 763-8013
- Nortel (MCS) | | FAX: (613) 763-5199
- | |
- | The opinions expressed are those of the author and do not necessarily |
- | represent the opinions of Nortel. |
-